package com.yaorange.module.security.service.impl;

import cn.hutool.core.lang.hash.Hash;
import cn.hutool.crypto.SecureUtil;
import com.yaorange.container.PermissionContainer;
import com.yaorange.exception.BusinessException;
import com.yaorange.module.security.entity.dto.LoginDTO;
import com.yaorange.module.security.entity.vo.MenuVO;
import com.yaorange.module.security.entity.vo.ResourcesVO;
import com.yaorange.module.security.service.AuthService;
import com.yaorange.module.system.entity.vo.PermissionTreeVO;
import com.yaorange.module.system.service.SysPermissionService;
import com.yaorange.module.system.service.SysUserService;
import com.yaorange.pojo.SysPermission;
import com.yaorange.pojo.SysUser;
import com.yaorange.response.enums.ResultCode;
import com.yaorange.utils.JwtUtil;
import com.yaorange.utils.ThreadLocalUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 *  认证、授权服务实现
 */
@Service
public class AuthServiceImpl implements AuthService {
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private JwtUtil jwtUtil;
    @Autowired
    private SysPermissionService sysPermissionService;
    @Autowired
    private PermissionContainer permissionContainer;
    @Override
    public String login(LoginDTO loginDTO) {
        // 调用持久层完成数据查询
        SysUser sysUser = sysUserService.findUserByName(loginDTO.getUsername());
        if(sysUser == null){
            // 认证失败
            throw new BusinessException(ResultCode.NOT_USER);
        }
        // 校验密码
        // 对传输的数据进行MD5加密
        String s = SecureUtil.md5(loginDTO.getPassword());
        if(!sysUser.getUserPassword().equals(s)){
            // 认证失败
            throw new BusinessException(ResultCode.NOT_USER);
        }
        // 令牌中需要携带的数据
        Map<String,Object> claims = new HashMap<String,Object>();
        // 编号/昵称/头像/是否管理员
        claims.put("id",sysUser.getUserId());
        claims.put("nickname",sysUser.getUserNickname());
        claims.put("avatar",sysUser.getUserAvatar());
        claims.put("admin",sysUser.getAdmin());
        // 生成令牌
        String token = jwtUtil.generateToken(claims);
        return token;
    }

    @Override
    public ResourcesVO getResources() {
        // 根据用户的编号获取用户的资源信息
        String sysId_admin = ThreadLocalUtil.get();
        if(!StringUtils.hasText(sysId_admin)){
            throw new BusinessException(ResultCode.FAIL);
        }
        String[] array = sysId_admin.split("-");
        // 用户编号
        Long sysId = Long.parseLong(array[0]);
        // 是否是管理员
        //Long admin = Long.parseLong(array[1]);

        // 根据用户编号获取用户资源
        List<SysPermission> permissionList = sysPermissionService.findPermissionsTreeByUserId(sysId);
        // 构建资源对象
        ResourcesVO resourcesVO =  buildResourcesVO(permissionList);


        // 将当前用户的权限保存缓存中
        permissionContainer.putPermission("LOGIN_USER_"+sysId,resourcesVO.getPermissions());
        return resourcesVO;
    }

    /**
     *  构建资源对象
     * @param permissionList
     * @return
     */
    private ResourcesVO buildResourcesVO(List<SysPermission> permissionList) {
        ResourcesVO resourcesVO = new ResourcesVO();
        // 获取权限表达式
        Set<String> psSet = permissionList.stream()
                .map(SysPermission::getPermExpression)
                .filter(StringUtils::hasText)
                .collect(Collectors.toSet());
        resourcesVO.setPermissions(psSet);


        // 构建路由树
        // 创建Map，用于封装权限对象
        HashMap<Long, MenuVO> menuVOMap = new HashMap<>();
        // 遍历 权限集合
        for (int i = 0; i < permissionList.size(); i++) {
            MenuVO menuVO = new MenuVO();
            SysPermission sysPermission = permissionList.get(i);
            menuVO.setTitle(sysPermission.getPermTitle());
            menuVO.setPath(sysPermission.getPermPath());
            menuVO.setComponent(sysPermission.getPermComponent());
            menuVO.setType(sysPermission.getPermType());
            menuVO.setChildren(new ArrayList<>());
            menuVOMap.put(sysPermission.getPermId(), menuVO);
        }

        // 构建权限树
        List<MenuVO> rootTreeVo = new ArrayList<>();
        for(SysPermission sysPermission:permissionList){
            // pid是null 则代表是父节点
            if(sysPermission.getPermPid() == null){
                MenuVO parentVo = menuVOMap.get(sysPermission.getPermId());
                rootTreeVo.add(parentVo);
            }else{
                // 子节点
                MenuVO parentVo = menuVOMap.get(sysPermission.getPermPid());
                parentVo.getChildren().add(menuVOMap.get(sysPermission.getPermId()));
            }
        }

        // TODO 缺少昵称 头像...

        resourcesVO.setMenus(rootTreeVo);
        return resourcesVO;
    }
}
